package luo.hui.jiang.tree;

/**
 * 二叉树案例
 * 类 HeroNode 是二叉树的单个节点
 * 类 BinaryTree 是二叉树
 *
 * 1.前序遍历，中序遍历，后序遍历。
 *      前序遍历：中左右
 *      中序遍历：左中右
 *      后序遍历：左右中
 *
 * 用前序遍历举例说明：
 *     主要使用的是递归的思路，将我们的二叉树从主节点出发。
 *     首先输出自己this。
 *     然后判断左子树是否为空，如果不为空，递归遍历左子树，这是什么意思呢？
 *     其实就是将左子树当（主节点），它会输出它自己，然后去看看它的左子树是否为空，如果不为空！
 *     那就会对它的左子树进行递归，那么这时就是将它的左子树当（主节点）。
 *     直到递归结束，也就是发现有某个节点的左子树为空了。
 *     然后对其右子树进行相同的操作。
 *     直到右子树递归结束，返回，父节点也进行右子树的递归。
 *     最后等右子树的递归全部完成后。
 *     前序遍历结束。
 *
 * @author 罗惠江
 * @version 1.0
 * @email 1511619294@qq.com
 * @date 2020/8/8 22:40
 */
public class BinaryTreeDemo {
    public static void main(String[] args) {
        // 先需要创建一颗二叉树
        BinaryTree binaryTree = new BinaryTree();
        // 创建需要节点
        HeroNode root = new HeroNode(1, "宋江");
        HeroNode node2 = new HeroNode(2, "吴用");
        HeroNode node3 = new HeroNode(3, "卢俊义");
        HeroNode node4 = new HeroNode(4, "林冲");
        HeroNode node5 = new HeroNode(5, "关胜");

        // 手动创建二叉树
        root.setLeft(node2);
        root.setRight(node3);
        node3.setRight(node4);
        node3.setLeft(node5);
        binaryTree.setRoot(root);

        // 测试
        System.out.println("中序遍历");
        binaryTree.preOrder();

        //测试
        System.out.println("中序遍历");
        binaryTree.infixOrder();

        //测试
        System.out.println("后序遍历");
        binaryTree.postOrder();
    }

}

// 创建我们的二叉树
class BinaryTree {
    private HeroNode root;

    public HeroNode getRoot() {
        return root;
    }

    public void setRoot(HeroNode root) {
        this.root = root;
    }

    // 前序遍历
    public void preOrder() {
        if (this.root != null) {
            this.root.preOrder();
        } else {
            System.out.println("二叉树为空，无法遍历");
        }
    }

    // 中序遍历
    public void infixOrder() {
        if (this.root != null) {
            this.root.infixOrder();
        } else {
            System.out.println("二叉树为空，无法遍历");
        }
    }

    // 后序遍历
    public void postOrder() {
        if (this.root != null) {
            this.root.postOrder();
        } else {
            System.out.println("二叉树为空，无法遍历");
        }
    }


}

// 创建了我们的 HeroNode 二叉树节点
class HeroNode {
    private int no;
    private String name;
    private HeroNode left;// 表示的是左子树
    private HeroNode right;// 表示的是右子树

    public HeroNode(int no, String name) {
        this.no = no;
        this.name = name;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public HeroNode getLeft() {
        return left;
    }

    public void setLeft(HeroNode left) {
        this.left = left;
    }

    public HeroNode getRight() {
        return right;
    }

    public void setRight(HeroNode right) {
        this.right = right;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", left=" + left +
                ", right=" + right +
                '}';
    }

    //  编写前序遍历的方法
    public void preOrder() {
        System.out.println(this);// 先输出父亲节点
        // 递归向坐姿数前序遍历
        if (this.left != null) {
            this.left.preOrder();
        }
        // 递归玩左子树后，开始递归遍历右子树
        if (this.right != null) {
            this.right.preOrder();
        }
    }

    // 中序遍历
    public void infixOrder() {
        // 递归向左子树中序遍历
        if (this.left != null) {
            this.left.infixOrder();
        }
        // 输出父节点
        System.out.println(this);
        if (this.right != null) {
            this.right.infixOrder();
        }
    }

    public void postOrder() {
        if (this.left != null) {
            this.left.postOrder();
        }
        if (this.right != null) {
            this.right.postOrder();
        }
        System.out.println(this);
    }
}
